home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 001a / seyon213.tz / seyon213 / seyon / SeTerm.c < prev    next >
C/C++ Source or Header  |  1993-04-10  |  9KB  |  353 lines

  1. /*
  2.  * This file is part of the Seyon, Copyright (c) 1992-1993 by Muhammad M.
  3.  * Saggaf. All rights reserved.
  4.  *
  5.  * See the file COPYING (1-COPYING) or the manual page seyon(1) for a full
  6.  * statement of rights and permissions for this program.
  7.  */
  8.  
  9. /*
  10.  * This file contains routines for Seyon's terminal. The main routine is
  11.  * terminal(), which reads characters from the terminal and sends them to the
  12.  * port. That routine also forks a child process that reads characters from
  13.  * the port and writes them to the temrinal. Once the parent receives SIGTERM
  14.  * (which should be sent by the grand parent), it kills the child and exits.
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <signal.h>
  20. #include <sys/types.h>
  21. #include <sys/wait.h>
  22.  
  23. #include <X11/Intrinsic.h>
  24.  
  25. #include "seyon.h"
  26. #include "SeDecl.h"
  27.  
  28. extern char     TtyReadChar();
  29. extern int      MdmReadStr();
  30.  
  31. extern FILE    *tfp,            /* terminal pointer */
  32.                *cfp;            /* capture file pointer */
  33. extern Boolean  capture;        /* are we capturing or not ? */
  34. extern int      tfd,            /* terminal descriptor */
  35.                 mainToTermPipe[];
  36.  
  37. void            send_tbyte(),
  38.                 toggle(),
  39.                 cleanup();
  40.  
  41. pid_t           readProcPid = 0; /* pid of child process */
  42.  
  43. /*---------------------------------------------------------------------------+
  44. | DoNothingHandler - handler for doing nothing.
  45. +---------------------------------------------------------------------------*/
  46.  
  47. void
  48. DoNothingHandler(sigNum)
  49.      int       sigNum;
  50. {
  51. #ifdef DEBUG
  52.   showf(">>> in DoNothingHandler, pid = %d, sig = %d", getpid(), sigNum);
  53. #endif
  54.  
  55.   /* Reinstall the signal handler */
  56.   signal(sigNum, DoNothingHandler);
  57. }
  58.  
  59. /*---------------------------------------------------------------------------+
  60. | TerminalKillHandler - handler for the terminal kill (SIGTERM).
  61. +---------------------------------------------------------------------------*/
  62.  
  63. void
  64. TerminalKillHandler(dummy)
  65.      int             dummy;
  66. {
  67.   signal(SIGTERM, SIG_IGN);
  68.  
  69.   /* Kill the child process and wait for it to die, sounds vicious, 
  70.      doesn't it? The child process is the read process from the port */
  71.  
  72.   if (readProcPid && kill(readProcPid, SIGTERM) == 0) 
  73.     while(wait((int*)0) < 0);
  74.   
  75.   fflush(tfp);
  76.   exit(0);
  77. }
  78.  
  79. /*---------------------------------------------------------------------------+
  80. | TerminalSuspendHandler - handler for the terminal suspension (SIGUSR1).
  81. +---------------------------------------------------------------------------*/
  82.  
  83. void
  84. TerminalSuspendHandler(sigNum)
  85.      int             sigNum;
  86. {
  87.   /* Don't deliver or stack (as pending) any more instances of the signal
  88.      until we've woken up (below) */
  89.   signal(sigNum, SIG_IGN);
  90.  
  91.   if (readProcPid) kill(readProcPid, sigNum);
  92.  
  93.   pause();
  94.  
  95. #ifdef DEBUG
  96.   showf(">>> Terminal %d woke up - good", getpid());
  97. #endif
  98.  
  99.   /* After waking up */
  100.  
  101.   if (readProcPid) kill(readProcPid, SIGCONT);
  102.  
  103.   /* Reinstall the signal handler */
  104.   signal(sigNum, TerminalSuspendHandler);
  105. }
  106.  
  107. /*---------------------------------------------------------------------------+
  108. | TerminalRefreshParametersHandler - handler for the terminal to get the 
  109. |                                    current session parameters (SIGUSR2).
  110. +---------------------------------------------------------------------------*/
  111.  
  112. void
  113. TerminalRefreshParametersHandler(sigNum)
  114.      int       sigNum;
  115. {
  116.   int        PutParameters();
  117.   void       GetParameters();
  118.  
  119.   /* Don't deliver or stack (as pending) any more instances of the signal
  120.      until we're finished with the work at hand */
  121.   signal(sigNum, SIG_IGN);
  122.  
  123.   GetParameters(NULL, mainToTermPipe);
  124.  
  125.   if (readProcPid && (PutParameters(mainToTermPipe) < 0 || 
  126.                       kill(readProcPid, sigNum) != 0))
  127.     SePError("Could not pipe parameters");
  128.  
  129.   /* Reinstall the signal handler */
  130.   signal(sigNum, TerminalRefreshParametersHandler);
  131. }
  132.  
  133. /*
  134.  * Terminal: main routine. Has two processes, one to read from terminal 
  135.  *           and send to the port and the other to do the oppsite.
  136.  */
  137.  
  138. void
  139. Terminal()
  140. {
  141.   char            c;
  142.  
  143.   /* Tell the program where to go when signals are received */
  144.   signal(SIGTERM, TerminalKillHandler);
  145.   signal(SIGUSR1, TerminalSuspendHandler);
  146.   signal(SIGUSR2, TerminalRefreshParametersHandler);
  147.   signal(SIGCONT, DoNothingHandler);
  148.   signal(SIGCHLD, SIG_DFL);
  149.  
  150.   /* Split into read and write processes */
  151.  
  152.   /* Child, read proc: read from port and write to tty */
  153.   if ((readProcPid = SeFork()) == 0)
  154.     PortToTty();
  155.  
  156.   /* Parent, write proc: read from tty and write to port */
  157.  
  158.   while (1)
  159.     if (TtyReadChar(tfd, &c) >= 0) send_tbyte(c);
  160.     else {
  161.       SeError("TTY read error. Terminal process exiting");
  162.       if (readProcPid && kill(readProcPid, SIGTERM) == 0) 
  163.         while(wait((int*)0) < 0);
  164.       ProcRequest(POPUP_ERROR, "TTY Read Error", "errReadError");
  165.       exit(1);
  166.     }
  167.   /*NOT REACHED*/
  168. }
  169.  
  170. /*
  171.  * Read from the port and write to the tty
  172.  */
  173.  
  174. void
  175. PortToTty()
  176. {
  177.   static char           zmSig[] = "**\030B00";
  178.   static char          *zmSigPtr = zmSig;
  179.   char                  buf[BUFSIZ], c;
  180.   int                   n, i;
  181.  
  182.   signal(SIGTERM, TerminalKillHandler);
  183.  
  184.   while (1) {
  185.  
  186.     /* Read incoming charaters and exit the process if a read error
  187.        is encountered */
  188.  
  189.     if ((n = MdmReadStr(buf)) < 0) {
  190.       SeError("Modem read error. Terminal process exiting");
  191.       ProcRequest(POPUP_ERROR, "Modem Read Error", "errReadError");
  192.       ProcRequest(KILL_TERM, "", "");
  193.       exit(1);
  194.     }
  195.  
  196.     /* Write incoming characters to the tty */
  197.     fwrite(buf, sizeof(char), n, tfp); 
  198.     fflush(tfp);
  199.  
  200.     for(i = 0; i < n; i++) {
  201.       c = buf[i];
  202.       
  203.       /* Write to capture file if capture is enabled */
  204.       if (capture) fputc(c, cfp);
  205.  
  206.       /* Look for Zmodem signature */
  207.       if (c != *zmSigPtr)
  208.         zmSigPtr = zmSig;
  209.       else if (*++zmSigPtr == '\0' && qres.autoZmodem) 
  210.         ProcRequest(START_AUTO_ZM, "Zmodem Auto-Download", "");
  211.  
  212.     } /* for... */
  213.   } /* while(1)... */
  214.   /*NOT REACHED*/
  215. }
  216.  
  217. /*
  218.  * send a translated character to the modem
  219.  */
  220.  
  221. void
  222. send_tbyte(c)
  223.      int             c;
  224. {
  225.   switch (c) {
  226.  
  227.     /*Translate new line to carriage return if newline translation mode is
  228.       in effect*/
  229.   case '\n':
  230.     switch (newlineTrMode) {
  231.     case 2:
  232.       c = '\r';
  233.       break;
  234.     case 3:
  235.       sendbyte('\r');
  236.     default:
  237.       break;
  238.     }
  239.     break;
  240.  
  241.     /*Translate backspace to delete if del translation mode is in effect*/
  242.   case 0x08:
  243.     if (qres.backspaceTranslation)
  244.       c = 0x7f;
  245.     break;
  246.  
  247.   default:
  248.     break;
  249.   }
  250.  
  251.   /*Send ESC before the character if meta key is pressed with the  character
  252.     and the meta key translation mode is on*/
  253.   if (qres.metaKeyTranslation && (c & 0x80)) {
  254.     sendbyte('\033');
  255.     sendbyte(c);
  256.   }
  257.  
  258.   /*Send the character to the port*/
  259.   else
  260.     sendbyte(c);
  261. }
  262.  
  263. /*---------------------------------------------------------------------------+
  264. | Routines to manipulate the terminal process. 
  265. +---------------------------------------------------------------------------*/
  266.  
  267. pid_t           termProcPid = 0; /* pid of the terminal process */
  268.  
  269. /*---------------------------------------------------------------------------+
  270. | StartTerminal - starts the terminal process.
  271. +---------------------------------------------------------------------------*/
  272.  
  273. void
  274. StartTerminal()
  275. {
  276.   if (termProcPid) return;
  277.  
  278.   if ((termProcPid = SeFork()) == 0)
  279.     {Terminal(); exit(1);}
  280. }
  281.  
  282. /*---------------------------------------------------------------------------+
  283. | KillTerminal - kills the terminal process.
  284. +---------------------------------------------------------------------------*/
  285.  
  286. void
  287. KillTerminal()
  288. {
  289.   void     (*oldSigHandler)();
  290.  
  291.   if (termProcPid == 0) return;
  292.   /* Make sure it's not suspended so that it can react to SIGTERM */
  293. /*  if (SuspContTerminal(TERM_CONTINUE) == 0) return;*/
  294.  
  295.   oldSigHandler = signal(SIGCHLD, SIG_DFL);
  296.  
  297.   /* Kill the child and wait for it to die */
  298.   if (termProcPid && kill(termProcPid, SIGTERM) == 0) 
  299.     {while(wait((int*)0) < 0); termProcPid = 0;}
  300.  
  301.   signal(SIGCHLD, oldSigHandler);
  302. }
  303.  
  304. /*---------------------------------------------------------------------------+
  305. | SuspContTerminal - suspends or resumes the terminal process.
  306. +---------------------------------------------------------------------------*/
  307.  
  308. int
  309. SuspContTerminal(state)
  310.      int state;
  311. {
  312.   /* This variable keeps track of whether 
  313.      the terminal is active or suspended */
  314.   static int termSuspended = 0;
  315.   
  316.   if (termProcPid == 0) return 0;
  317.  
  318.   if (state == TERM_CONTINUE) {
  319.     if (termProcPid && kill(termProcPid, SIGCONT) == 0) 
  320.       termSuspended = 0;
  321.     return 1;
  322.   }
  323.  
  324.   if (termSuspended) return 0;
  325.   if (termProcPid && kill(termProcPid, SIGUSR1) == 0) 
  326.     {termSuspended = 1; return 1;}
  327.   else
  328.     return 0;
  329. }
  330.  
  331. int
  332. TerminalRefreshParameters()
  333. {
  334.   int    PutParameters();
  335.  
  336.   if (termProcPid && (PutParameters(mainToTermPipe) < 0 || 
  337.                       kill(termProcPid, SIGUSR2) != 0))
  338.     return -1;
  339.   else return 0;
  340. }
  341.  
  342. /*
  343.  * Restart the terminal process (refresh) by killing it and starting a new
  344.  * one
  345.  */
  346.  
  347. void
  348. RestartTerminal()
  349. {
  350.   KillTerminal();
  351.   StartTerminal();
  352. }
  353.